﻿bob.ns.setNs('bob.fn.tests', {

    TestFn: function () {

        this.test_Overload = function () {

            var fn1 = function (retVal) {
                return retVal;
            };

            var fn2 = function () {
                return fn1('Bob');
            };

            var getName = new bob.fn.Overload();

            bob.assert.throwsError(function () { getName.add(); });

            getName.add(function () { return arguments.length > 0; }, fn1);
            getName.add(function () { return true; }, fn2);

            bob.assert.equals('Bob', getName.call());
            bob.assert.equals('Tengiz', getName.call('Tengiz'));
        };

        this.test_overloadFunction = function () {

            bob.assert.throwsError(function () { bob.fn.overloadFunction(); });
            bob.assert.throwsError(function () { bob.fn.overloadFunction([]); });
            bob.assert.throwsError(function () { bob.fn.overloadFunction([{}]); });

            var fn1 = function (retVal) {
                return retVal;
            };

            var fn2 = function () {
                return fn1('Bob');
            };

            var getName = new bob.fn.overloadFunction([
                {
                    condition: function () {
                        return arguments.length > 0;
                    },
                    overload: fn1
                },
                {
                    condition: function () {
                        return true;
                    },
                    overload: fn2
                }]);

            bob.assert.equals('Bob', getName());
            bob.assert.equals('Tengiz', getName('Tengiz'));

        };

        this.test_fixedObjectFunction = function () {

            //overload with function.
            var obj = {};
            var func = function () {
                bob.assert.equals(obj, this, '0');
            };

            var fixed = bob.fn.fixedObjectFunction(obj, func);
            bob.assert.isTrue(bob.utils.isFunction(fixed), '1');
            fixed();

        };

        this.test_fixedObjectFunctionWithStr = function () {

            //overload with property name.
            var obj = {
                fn: function () {
                    bob.assert.equals(obj, this, '2');
                }
            };

            var fixed = bob.fn.fixedObjectFunction(obj, 'fn');
            bob.assert.isTrue(bob.utils.isFunction(fixed, '3'));
            fixed.apply({});

        };

        this.test_getArgumentNames = function () {

            bob.assert.throwsError(function () { bob.fn.getArgumentNames(null); }, '0');
            bob.assert.throwsError(function () { bob.fn.getArgumentNames({}); }, '1');

            var fn = function () { };
            var argNames = bob.fn.getArgumentNames(fn);
            bob.assert.isTrue(bob.utils.isArray(argNames), '2');
            bob.assert.equals(0, argNames.length, '3');

            var fn = function (a) { };
            var argNames = bob.fn.getArgumentNames(fn);
            bob.assert.isTrue(bob.utils.isArray(argNames), '4');
            bob.assert.isTrue(bob.collections.extensions.equals.call(['a'], argNames), '5');

            var fn = function (a, b, c, d, e, f) { };
            var argNames = bob.fn.getArgumentNames(fn);
            bob.assert.isTrue(bob.utils.isArray(argNames), '6');
            bob.assert.isTrue(bob.collections.extensions.equals.call(['a', 'b', 'c', 'd', 'e', 'f'], argNames), '7');
        };

        this.test_namedArgFunction = function () {

            bob.assert.throwsError(function () { bob.fn.namedArgFunction(null) }, '0');
            bob.assert.throwsError(function () { bob.fn.namedArgFunction({}) }, '1');

            var fn = function () {
                bob.assert.equals(0, arguments.length, '2');
            };
            var wrapper = bob.fn.namedArgFunction(fn);
            bob.assert.isTrue(bob.utils.isFunction(wrapper), '3');
            wrapper({ a: 'b' });

            var arg = { a: 1, b: '2' };
            var fn = function (a, b) {
                bob.assert.equals(arg.a, a, '4');
                bob.assert.equals(arg.b, b, '5');
                bob.assert.equals(2, arguments.length, '6');
            };
            var wrapper = bob.fn.namedArgFunction(fn);
            bob.assert.isTrue(bob.utils.isFunction(wrapper), '7');
            wrapper(arg);

            var arg = undefined;
            var fn = function (a, b) {
                bob.assert.isUndefined(a, '8');
                bob.assert.isUndefined(b, '9');
                bob.assert.equals(0, arguments.length, '10');
            };
            var wrapper = bob.fn.namedArgFunction(fn);
            bob.assert.isTrue(bob.utils.isFunction(wrapper), '7');
            wrapper(arg);
            wrapper();
        };

    }

});